#include "lock/monitor.h"
#include "assert.h"
#include "mmu.h"

void
monitor_init(monitor_t* m, size_t cvNum) {
    assert(cvNum > 0);
    semaphore_init(&(m->mutex), 1);
    semaphore_init(&(m->next), 0);
    m->nextCount = 0;
    m->cv = kmalloc(sizeof(condvar_t) * cvNum);
    assert(m->cv != NULL);
    for (int i = 0; i < cvNum; ++i) {
        m->cv[i].count = 0;
        semaphore_init(&(m->cv[i].sem), 0);
        m->cv[i].owner = m;
    }
}

void
cond_signal(condvar_t* cv) {
    if (cv->count > 0) {
        monitor_t* m = cv->owner;
        ++m->nextCount;
        semaphore_release(&(cv->sem));
        semaphore_acquire(&(m->next));
        --m->nextCount;
    }
}

void
cond_wait(condvar_t* cv) {
    ++cv->count;
    monitor_t* m = cv->owner;
    if (m->nextCount > 0)
        semaphore_release(&(m->next));
    else
        semaphore_release(&(cv->sem));
    --cv->count;
}